/**
 * Application Layout
 * by Jozef Sakalos, aka Saki
 * http://extjs.com/learn/Tutorial:Application_Layout_for_Beginners
 */
/**
 * Design of the application
 * by Mel Meng
 * 10/8/2009
 * This application has the following functions:
 * 1. Display the PACP database
 * 2. Search the PACP database
 * Below is the client design
 *
 * ---------------------------------
 *          North                   |
 * Search Tool            Map Query |
 *----------------------------------|
 *   West     |      Run  Summary   |
 *            | ------------------- | <-Center are tabs:
 *   Run List |  Defect |  Defect   |
 *            |  List   |  Summary  |
 *            |         | --------  |
 *            |         |  Video    |
 *            |         |           |
 *            |         |           |
 * ---------------------------------
 * Ext Components
 *  1. run_panel
 *  2. tabs
 *  3. defect_panel
 *    a. run_summary
 *    b. defect_list
 *    c. defect summary
 *    d. video_panel
 *  5.tool_panel
 *  6. toos
 *    a. help window
 *    b. map window
 *    c. query window
 *
 *  Model
 *  1. run_store
 *  2. detail_store
 *  3. query_store (a query tree)
 *
 *
 *
 *
 *
 */
// reference local blank image
//Ext.BLANK_IMAGE_URL = '../ext/resources/images/default/s.gif';

// create namespace
Ext.namespace('pacp');

// create application
pacp.app = function(){
    // do NOT access DOM from here; elements don't exist yet
    // private functions
    // create the Data Store
    //run_store, the only data source for run information
    
    /*
     * Data Sources
     */
	var RUNS_FLDS = [{
            name: 'Date',
            type: 'date',
            dateFormat: 'Ymd'
        }, 'dia', 
		'Rim_to_Grade_(D)', 'City', 'Upstream_MH', 
	'PO_Number', 'Rim_to_Invert_(D)', 'Surveyor_Name', 'Pipe_Joint_Length', 'Structural_Grading', 'Pre-Cleaning', 'Year_Renewed', 'Location_Details', 'Additional_Info', 'Grade_to_Invert_(U)', 'Year_Laid', 'Length_Surveyed', 'Material', 'Direction_of_Survey', 'Rim_to_Invert_(U)', 'Grade_to_Invert_(D)', 'Location_Code', 'Weather', 'RunID', 'MPEGPath', 'Pipe_Segment_Reference', 'Purpose', 'Customer', 'DiscName', 'Height_(Diameter)', 'Certificate_Number', 'Time', 'Date_Cleaned', 'Drainage_Area', 
	'DesignSlope', 'Width', 'Downstream_MH', 'Media_Label', 'EndFrame', 'PIPETECHID', 'Shape', 'Sewer_Use', 'Lining_Method', 'Flow_Control', 'Sewer_Category', 'Owner', 'Total_Length', 'Rim_to_Grade_(U)', 'Street'];
    var run_store = new Ext.data.JsonStore({
        root: 'runs',
        totalProperty: 'totalcount',
        idProperty: 'RunID',
        error: 'error',
        id: 'RunID',
        //this is copied from the model of the pylons 
        fields: RUNS_FLDS,
        baseParams: {
            limit: 20
        },
        
        // load using script tags for cross domain, if the data in on the same domain as
        // this page, an HttpProxy would be better
        proxy: new Ext.data.HttpProxy({
            url: '/query/run',
            method: 'GET'
        })
    });//end of run store
    
	var DETAILS_FLDS = ['DetailID', 'RunID', 'VideoFrameNumber', 'Footage', 'ConditionCode', 'Continuous', 'Position_From', 'Position_To', 'Percentage', 'Comment', 'Dimension1', 'Dimension2', 'foot'];

    /*
     * End of data sources
     */
    /*
     * Components --- Tools
     */
    //help_window, display the help based on the html file name
    var help_window = function(url){
        new Ext.Window({
            height: 800,
            width: 500,
            layout: 'fit',
            id: 'win-help',
            x: 10,
            y: 10,
            autoScroll: true,
            modal: false,
            title: 'Help',
            //hard coded path
            autoLoad: 'html/help/' + url
        }).show();
    };//end of help_window
    //map_window, shows the map, experimental, not implemented yet
    var map_window = function(x, y, att){
        new Ext.Window({
            title: "Maps",
            height: 280,
            width: 450,
            layout: "fit",
            items: [{
                xtype: "gx_mappanel",
                layers: [layer = new OpenLayers.Layer.WMS("OSM", ["http://t1.hypercube.telascience.org/tiles?", "http://t2.hypercube.telascience.org/tiles?", "http://t3.hypercube.telascience.org/tiles?", "http://t4.hypercube.telascience.org/tiles?"], {
                    layers: 'osm-4326',
                    format: 'image/png'
                })],
                zoom: 10,
                center: new OpenLayers.LonLat(-83, 39.9618)
            }]
        }).show();
    };//end of map_window
    //validation window
    var valid_win = function(v){
        var win = new Ext.Window({
            height: 230,
            width: 350,
            layout: 'fit',
            id: 'win-valid',
            modal: true,
            defaultType: 'textfield',
            title: 'You query is not well formed...',
            items: [new Ext.Panel({
                frame: true,
                bodyStyle: 'padding:1px 1px 0',
                width: 350,
                items: [{
                    id: 'valid-notice',
                    html: 'Validation text'
                }, {
                    id: 'val-textarea',
                    xtype: 'textarea',
                    height: 200,
                    width: 350,
                    value: v
                
                }],
                
                buttons: [{
                    text: 'Try again',
                    handler: function(){
                        var ta = Ext.getCmp('val-textarea');
                        
                        valid_query(ta.getValue());
                    }
                }, {
                    text: 'Cancel',
                    handler: function(){
                        Ext.getCmp('win-valid').close();
						Ext.getCmp('searchtool').setValue('');
						Ext.getCmp('searchtool').onTrigger1Click();
                    }
                }, {
                    text: 'Help',
                    handler: function(){
                        help_window('pql.htm');
                    }
                }]
            })]
        }).show();
        
    };//end of valid_win
    //function valid_query
    var valid_query = function(v){
    
        Ext.Ajax.request({
            url: 'query/validate',
            params: {
                q: v
            },
            success: function(response){
                var obj = Ext.util.JSON.decode(response.responseText);
                xx = obj;
                if (obj.success) {
                
                    var vwin = Ext.getCmp('win-valid');
                    if (vwin) {
                        vwin.close();
                    };
                    var st = Ext.getCmp('searchtool');
                    st.setValue(v);
                    if (st.hasSearch == false) {
                        st.hasSearch = true;
                        st.triggers[0].show();
                        
                    }
                    
                    var o = {
                        start: 0
                    };
                    
                    st.store.baseParams = st.store.baseParams ||
                    {};
                    st.store.baseParams[st.paramName] = v;
                    st.store.reload({
                        params: o
                    });
                    st.hasSearch = true;
                    st.triggers[0].show();
                    
                    
                    
                    
                }
                else {
					var vwin = Ext.getCmp('win-valid');
					if (!vwin) {
						valid_win(v);
					};
                    
                    var detailEl = Ext.getCmp('valid-notice').body;
                    var tpl = new Ext.XTemplate('<tpl><h1>Please fix the errors in red to continue</h1>','<tpl for="results">',  '<span class="{status}">{code},{status}</span><br/>', '</tpl></tpl>');
                    tpl.overwrite(detailEl, obj);
                    detailEl.slideIn('l', {
                        stopFx: true,
                        duration: .2
                    });
                    
                    
                    
                    
                }
                
                
            }
        });
        
    };//end of valid_query
    //search_tool, the search box
    var search_tool = new Ext.ux.form.SearchField({
        id: 'searchtool',
        store: run_store,
        emptyText: 'Search...',
        width: 300,
        //overwrite default tool
        onTrigger2Click: function(){
        
            var v = this.getRawValue();
            if (v.length < 1) {
                this.onTrigger1Click();
                return;
            };
            valid_query(v)
        }
        
        
    });//end of search_tool
    //show v in the search tool and run the search		
    var do_search = function(v){
        var st = Ext.getCmp('searchtool');
        st.setValue(v);
        st.onTrigger2Click();
    };//end of do search
    //top_toolbar
    var top_toolbar = new Ext.Toolbar({
        cls: 'top-toolbar',
        items: ['Search: ', search_tool, {
            tooltip: 'Help',
            iconCls: 'icon-help',
            handler: function(){
                help_window('pql.htm');
            }
            
        }, '-', {
            iconCls: 'icon-map',
            //                text: 'Map',
            tooltip: 'Map',
            handler: function(){
				alert('current disabled, need to load GeoEXT + Openlayers')
//                map_window(1, 2, 3);
            }
        }]
    });//end of top_toolbar
    /*
     * End of Tools
     */
    /*
     * Panels
     */
    //north, the header
    var header = new Ext.Panel({
        border: false,
        layout: 'anchor',
        region: 'north',
        cls: 'docs-header',
        height: 60,
        items: [{
            xtype: 'box',
            el: 'header',
            border: false,
            anchor: 'none -25'
        }, top_toolbar]
    });//end of header
    //west: run_panel
    
    //templates
    // Custom rendering Template for the View
    var run_tpl = new Ext.XTemplate('<tpl for=".">', '<div class="run-summary">', '<span class = "right"> {Date:date("M j, Y")}<br/>{Weather}, {Pre-Cleaning}</span>', '<h4 style="color:blue;" class="{Direction_of_Survey}">{PIPETECHID}</h4>', '<p>@{Street}<br/>', '{dia}in. {Material}, {Length_Surveyed} ft </p><br/>', '<tpl if="Additional_Info!=null"><span class="comment">{Additional_Info}</span></tpl>', '</div></tpl>');
    var detail_tpl = new Ext.XTemplate('<tpl for=".">', '<div class="defect-summary">', '<h3><span>', '@{Footage}ft <br/>', '<tpl if="Position_From!=null">{Position_From}</tpl>', '<tpl if="Position_To!=null">-{Position_To}</tpl>', '</span>', '<tpl if="this.startWith(Continuous, &quot;S&quot;)==true"><p class="Downstream">{ConditionCode}({Continuous})</p></tpl>', '<tpl if="this.startWith(Continuous, &quot;F&quot;)==true"><p class="Upstream">{ConditionCode}({Continuous})</p></tpl>', '<tpl if="Continuous==null">{ConditionCode}</tpl>', '<tpl if="Position_From!=null"><img style="align:right;" alt="text" src="clock.jpg"/></tpl>', '</h3>', '<tpl if="Comment!=null">{Comment}</tpl>', '<tpl if="Comment==null"><br/></tpl>', '</div></tpl>', {
        // XTemplate configuration:
        compiled: true,
        disableFormats: true,
        // member functions:
        startWith: function(x, y){
            if (x == null) {
                return false
            }
            else {
                return x.substr(0, 1) == y;
            }
        }
    });//end of detail_tpl
    // pluggable renders
    function renderSummary(value, p, record){
        return run_tpl.applyTemplate(record.data);
        
        
    };//end of renderSummary
    function renderDate(value, p, r){
        return String.format('{0}<br/> {1}, {2}', value.dateFormat('M j, Y'), r.data.Weather, r.data['Pre-Cleaning']);
    }; //end of renderDate
    function renderDetail(value, p, r){
    
        if (r.data.Continuous) {
            c_flag = r.data.Continuous.substr(0, 1);
        }
        else {
            c_flag = null;
        };
        
        html = '';
        if (c_flag == 'S') {
            html = '<p class="Downstream">' + r.data.ConditionCode + '(' + r.data.Continuous + ')</p>';
        }
        else 
            if (c_flag == 'F') {
                html = '<p class="Upstream">' + r.data.ConditionCode + '(' + r.data.Continuous + ')</p>';
            }
            else {
                html = r.data.ConditionCode;
            };
        
        if (r.data.Comment) {
            c = r.data.Comment;
        }
        else {
            c = ''
        };
        return '<h3>' + html + '</h3>' + c;
    }; //end of renderDetail
    function renderFootage(value, p, r){
        t = '';
        if (r.data.Position_From) {
            t = r.data.Position_From;
        };
        if (r.data.Position_To) {
            t = t + '-' + r.data.Position_To;
        };
		if (r.data.Footage) {
			var f = r.data.Footage;
		} else {
			f = ''
		};

        return '@' + f + 'ft <br/> ' + t
        
    };
    
    var run_panel = new Ext.grid.GridPanel({
        width: 300,
        store: run_store,
        trackMouseOver: true,
        disableSelection: true,
        loadMask: true,
        
        // grid columns
        columns: [{
            header: "Summary",
            dataIndex: 'PIPETECHID',
            width: 250,
            renderer: renderSummary,
            sortable: true
        }],
        
        // customize view config
        sm: new Ext.grid.RowSelectionModel({
            singleSelect: true
        }),
        
        viewConfig: {
            forceFit: true
        },
        
        // paging bar on the bottom
        tbar: new Ext.PagingToolbar({
            pageSize: 25,
            store: run_store,
            displayInfo: true,
            displayMsg: '{0} - {1} of {2}',
            emptyMsg: "No Runs to display"
        })
    });//end of run panel as grid
    //center: tabs
    var tabs = new Ext.TabPanel({
        resizeTabs: true, // turn on tab resizing
        minTabWidth: 115,
        tabWidth: 170,
        activeTab: 0,
        listeners: {
            //when the tab changes, try to select the corresponding run in the list 
            'tabchange': function(tabPanel, tab){
                var runid = parseInt(tab.id.replace('tab', ''));
                var rnum = run_panel.getStore().indexOfId(parseInt(runid));
                run_panel.getSelectionModel().selectRow(rnum);
            }
            
        },
        plugins: new Ext.ux.TabCloseMenu(),
        items: {
            id: 'welcome-panel',
            title: 'PACP Viewer Home',
            autoLoad: 'html/welcome.htm',
            height: 800,
            autoScroll: true,
            closable: false
        }
    });
    
    /*
     * Defect Panel
     */
    //defect_list, render a list of defects using the runid, and the store
    var defect_list = function(runid, store){
        var x = new Ext.grid.GridPanel({
            width: 200,
            title: 'Defects List:',
            id: 'table' + runid,
            broder: false,
            store: store,
            trackMouseOver: true,
            disableSelection: true,
            loadMask: true,
            
            // grid columns
            columns: [{
                header: "Summary",
                dataIndex: 'ConditionCode',
                width: 100,
                renderer: renderDetail,
                sortable: true
            }, {
                header: "Footage",
                dataIndex: 'foot',
                width: 50,
                renderer: renderFootage,
                sortable: true
            }],
            
            // customize view config
            sm: new Ext.grid.RowSelectionModel({
                singleSelect: true
            }),
            
            viewConfig: {
                forceFit: true,
                autoScroll: true
            }
        });//end of x
        return x;
    };
    //video_panel, generate the html for the flash video
    var video_panel = function(runid, pid){
        //html for the flash object
        so = new SWFObject('/lib/jwplayer/player.swf', 'media' + runid, '400', '300', '9');
        so.addParam('allowfullscreen', 'true');
        so.addParam('allowscriptaccess', 'always');
        so.addParam('wmode', 'opaque');
        so.addVariable('file', '/flv/' + pid + '.flv');
        return so.getSWFHTML();
        
    };//end of video_panel
    //show_defect function, trigger when a row in the run list is selected
    var show_defect = function(sm, rowIdx, r){
        //when the run is clicked,register in history
        Ext.History.add(r.data.RunID);
        //select the run in run_list
        var runid = r.data.RunID;
        var ptid = r.data.PIPETECHID;
        var tab = Ext.getCmp('tab' + runid);
        if (tab) {
            //if the tab already exists
            tabs.setActiveTab(tab);
        }
        else {
            //each tab has a new store
            var detail_tmp_store = new Ext.data.JsonStore({
                root: 'details',
                totalProperty: 'totalcount',
                idProperty: 'DetailID',
                id: 'DetailID',
                fields: DETAILS_FLDS,
                baseParams: {
                    limit: 20
                },
                proxy: new Ext.data.HttpProxy({
                    url: '/detail',
                    method: 'GET'
                })
            });//end of detail tmp store
            //register the on load event to update the title with total defects
            detail_tmp_store.on('load', function(){
                defect_list_panel.setTitle(detail_tmp_store.totalLength + ' Defects');
            });
            
            
            
            //defect list panel on each tab
            var defect_list_panel = defect_list(runid, detail_tmp_store);
            //create a new defect panel
            var defect_panel = function(ptid, runid, defect_list_panel){
                return {
                    title: ptid,
                    id: 'tab' + runid,
                    layout: 'border',
                    border: false,
                    autoScroll: true,
                    closable: true,
                    items: [{
                        region: 'north',
                        height: 100,
                        border: false,
                        id: 'runsummary' + runid
                        //                        html: html_text
                    }, {
                        region: 'west',
                        layout: 'fit',
                        border: false,
                        width: 250,
                        margins: '0 0 0 0',
                        cmargins: '0 0 0 5',
                        bodyStyle: 'padding:10px;',
                        autoScroll: true,
                        items: [defect_list_panel]
                    
                    }, {
                        region: 'center',
                        width: 400,
                        border: false,
                        margins: '0 0 0 0',
                        cmargins: '5 5 5 5',
                        bodyStyle: 'padding:10px;',
                        forceLayout: true,
                        items: [{
                            id: 'defect' + runid,
                            height: 50,
                            border: false
                        
                        }, {
                            id: 'mediaspace' + runid,
                            border: false
                        }]
                    }]
                }
                
            };//end of defect panel
            //render the defect panel
            tabs.add(defect_panel(ptid, runid, defect_list_panel)).show();
            //once the panel is created, we can populate the data in different regions.
            //a simple tpl that passes html
            var simple_tpl = new Ext.XTemplate('<tpl>{html}</tpl>');
            //run summary
            var run_summary = Ext.getCmp('runsummary' + runid);
            run_tpl.overwrite(run_summary.body, r.data);
            //slide effects
            Ext.get('runsummary' + runid).slideIn('r', {
                duration: 0.6
            });
            //render the flash player
            //html for the flash object
            var flash_html = video_panel(runid, ptid);
            var flash_panel = Ext.getCmp('mediaspace' + runid);
            simple_tpl.overwrite(flash_panel.body, {
                html: flash_html
            });
            
            //defect summary
            html_data = {
                html: '<=Click on the defect to show details.'
            };
            
            simple_tpl.overwrite(Ext.getCmp('defect' + runid).body, html_data);
            //slide in effects
            Ext.get('defect' + runid).slideIn('r', {
                duration: 0.6
            });
            
            //register click event on defect list panel after it is rendered
            defect_list_panel.getSelectionModel().on('rowselect', function(sm, rowIdx, r){
                //show the summary of the defect
                var defect_summary_panel = Ext.getCmp('defect' + runid);
                detail_tpl.overwrite(defect_summary_panel.body, r.data);
                //slide in effects
                Ext.get('defect' + runid).slideIn('l', {
                    duration: 0.1
                });
                //jump to the corect time in the video
                var player = document.getElementById('media' + runid);
                //make sure it plays, otherwise the seek won't work
                player.sendEvent("PLAY", "true");
                player.sendEvent('SEEK', r.data.VideoFrameNumber / 29.9);
                
            });//end of detail_tab_panel click event
            //load the data
            detail_tmp_store.load({
                params: {
                    limit: 20,
                    start: 0,
                    query: runid
                }
            });//end of detail_tmp_store.load
        };//end of else
            };//end of show_defect
    // public space
    return {
        // public properties, e.g. strings to translate
        
        // public methods
        init: function(){
            //viewport 
            var viewport = new Ext.Viewport({
                layout: 'border',
                items: [header, {
                    region: 'south',
                    border: true,
                    html: '<div style="text-align: center;font-size: 80%;color:black;">Miller Kelton I&I Project - PACP Data Viewer by Mel Meng May 2009, <a href="http://www.dlz.com">DLZ</a>. ymeng@dlz.com<div>'
                
                }, {
                    region: 'west',
                    layout: 'fit',
                    split: true,
                    width: 300,
                    minSize: 175,
                    maxSize: 400,
                    collapseMode: 'mini',
                    collapsible: true,
                    autoScroll: false,
                    
                    layoutConfig: {
                        animate: true
                    },
                    items: [run_panel]
                }, {
                    region: 'center',
                    layout: 'fit',
                    border: false,
                    collapsible: true,
                    id: 'img-detail-panel',
                    split: true,
                    width: 670,
                    items: [tabs]
                }]
            });//end of viewport
            //show a list of runs
            run_store.load({
                params: {
                    start: 0,
                    limit: 20
                }
            });//end of run_store.load
            //Initilization....
            //tooltips
            Ext.QuickTips.init();
            //history
            var tokenDelimiter = ':';//not used yet, maybe use it in the future.
            Ext.History.init();
            
            
            //add listener
            /*
             * History
             * History remembers which run is selected by storing the runid
             */
            //select_run_by_id, pass the runid, then select the row in the run_panel
            var select_run_by_id = function(RunID){
                var rnum = run_panel.getStore().indexOfId(parseInt(RunID));
                run_panel.getSelectionModel().selectRow(rnum);
            };//end of select_run_by_id
            Ext.History.on('change', function(token){
                if (token) {
                    var parts = token.split(tokenDelimiter);
                    var runID = parts[0];
                    select_run_by_id(runID);
                }
            });//end of ext.history.on
            /*
             * Click on a run in the run_panel
             * triggers to display defect panel in a tab
             */
            //register click event
            run_panel.getSelectionModel().on('rowselect', show_defect);
            
        }//end of init
    }//end of return;
}(); // end of app
// end of file


